package com.apes.autoparts.supplier.jikugroup;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.apes.autoparts.supplier.platform.SupplierPlatformItem;
import com.apes.autoparts.supplier.platform.SupplierPlatformItemRepository;
import com.apes.autoparts.supplier.todo.SupplierPlatformTodoService;
import com.apes.framework.api.DomainService;
import com.apes.framework.api.SpringManager;
import com.apes.framework.jpa.generator.service.SequenceService;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.util.CronExpression;
import com.apes.framework.util.DateUtil;
import com.apes.framework.util.MapUtil;
import com.apestech.framework.json.JSON;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.text.ParseException;
import java.util.*;
import java.util.stream.Collectors;

//
///**
// * Created by lishikun on 2021/3/15 14:30
// */
@Service("jiKuGroupService")
public class JikuGroupService<T, R> extends JikuGroupApi<T, R> {

    @Autowired
    SupplierPlatformItemRepository supplierPlatformItemRepository;
    @Autowired
    JiKuGroupRepository jiKuGroupRepository;
    @Autowired
    private SupplierPlatformTodoService todoService;
    @Autowired
    SequenceService sequenceService;
    // 重点更新字段 品牌，产地，配件编码
    private final List<String> importantFields = Arrays.asList("partsBrandName", "originPlace", "partsCode");
    public void handHeap(SimpleRequest request) {
        JSONObject param = request.getJO();
        JSONArray jsonArray = param.getJSONArray("partsDTOs");
//        JSONArray jsonArray = param.getJSONArray("data");
        SupplierPlatformItem supplierPlatformItem = supplierPlatformItemRepository.findOne(param.getString("supplierPlatformItem"));
        List<String> ids = jsonArray.stream().map(v -> {
            JSONObject json = (JSONObject) v;
            return String.valueOf(Math.abs(json.getIntValue("partsId")));
        }).collect(Collectors.toList());
//
        // 获取缓存表的配件id
        Map map = new HashMap();
        if (ids != null && ids.size() != 0)
            jiKuGroupRepository.findByIdsAndSupplierPlatformItem(ids, supplierPlatformItem.getId()).forEach(jiKuGroup -> {
                map.put(jiKuGroup.getPartsId().toString(), MapUtil.mapped(jiKuGroup));
            });
        // 获取属于新建的数据
        JSONArray newJiKuGroup = jsonArray.stream().filter(v -> {
            JSONObject json = (JSONObject) v;
            if (map.get(json.getString("partsId")) == null)
                return true;
            return false;
        }).collect(Collectors.toCollection(JSONArray::new));
        // 获取属于更新的数据
        JSONArray updateJiKuGroup = jsonArray.stream().filter(v -> {
            JSONObject json = (JSONObject) v;
            if (map.get(json.getString("partsId")) != null)
                return true;
            return false;
        }).collect(Collectors.toCollection(JSONArray::new));
        saveUpdateData(updateJiKuGroup, supplierPlatformItem, map);
        saveCreateData(newJiKuGroup, supplierPlatformItem);
    }

    private void saveUpdateData(JSONArray jsonArray, SupplierPlatformItem supplierPlatformItem, Map map) {
        List<JiKuGroup> jiKuGroups = new ArrayList<>();
        JSONArray importantAttribute = new JSONArray();
        JSONArray update = new JSONArray();
        JSONArray deleteData = new JSONArray();

        for (Object o : jsonArray) {
            JSONObject json = (JSONObject) o;
            Map oldJiKuGroup = (Map) map.get(json.getString("partsId"));
            JiKuGroup cacheJiKuGroup = jiKuGroupRepository.findOne(oldJiKuGroup.get("id").toString());
            jsonToJiKuGroup(json, cacheJiKuGroup);
            // 只要有在销商品，都不会走下架路径
            if (json.getJSONArray("stockDTOs").stream().filter(dto -> {
                return ((JSONObject)dto).getBoolean("onSale");
            }).count() == 0) {
                deleteData.add(json);
            } else if (checkImportantUpdate(json, oldJiKuGroup))
                importantAttribute.add(json);
            else {
                update.add(json);
            }
            jiKuGroups.add(cacheJiKuGroup);
        }
        todos(importantAttribute, supplierPlatformItem,"importUpdate", map);
        todos(update, supplierPlatformItem,"update", map);
        todos(deleteData, supplierPlatformItem,"delete", map);
        jiKuGroupRepository.save(jiKuGroups);
    }




    private void saveCreateData(JSONArray newJiKuGroup, SupplierPlatformItem supplierPlatformItem) {
        List<JiKuGroup> jiKuGroups = JSONArray.parseArray(newJiKuGroup.toString(), JiKuGroup.class);
        for (JiKuGroup jiKuGroup : jiKuGroups) {
            jiKuGroup.setSupplierPlatformItem(supplierPlatformItem);
        }


        todos(newJiKuGroup, supplierPlatformItem,"create" , new HashMap<>());
        jiKuGroupRepository.saveAll(jiKuGroups);
    }

    private void deleteData(SupplierPlatformItem supplierPlatformItem) {
        List condition = new ArrayList();
        condition.add(MapUtil.mapper("field","id", "operator", "EQ", "value", "auto.supplierPlatform.synTotalTaskJiKuGroup"));
        List list = ((Page<Object>) SpringManager.getBean(DomainService.class).invoke("schedule.task.findAll",
                MapUtil.mapper("condition", condition, "size", 20, "page", 0))).getContent();
        if (list == null || list.size() == 0) return;
        Map task = MapUtil.mapped(list.get(0));
        List<Map> cronExpression = jiKuGroupRepository.findBySupplierPlatformItemAndNotUpdate(supplierPlatformItem.getId(), getHour(task.get("cronExpression").toString()) * 2);
        if (cronExpression.size() == 0) return;
        List<Map> newList= new ArrayList<>();
        for (Map map : cronExpression) {
            Map newMap = new HashMap(map);
            newMap.put("pjid", newMap.get("pjid"));
            newList.add(newMap);
        }
        try {
            todos(JSONArray.parseArray(JSON.toJSONString(newList)), supplierPlatformItem, "delete", new HashMap());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        jiKuGroupRepository.deleteBySupplierPlatformItemAndNotUpdate(supplierPlatformItem.getId(),
                getHour(task.get("cronExpression").toString()) * 2);
    }

    private void jsonToJiKuGroup(JSONObject json, JiKuGroup cacheJiKuGroup) {
        cacheJiKuGroup.setCarBrandName(json.getString("carBrandName"));
        cacheJiKuGroup.setOriginPartsCode(json.getString("originPartsCode"));
        cacheJiKuGroup.setOriginPlace(json.getString("originPlace"));
        cacheJiKuGroup.setPartsBrandName(json.getString("partsBrandName"));
        cacheJiKuGroup.setPartsCategoryName(json.getString("partsCategoryName"));
        cacheJiKuGroup.setPartsCode(json.getString("partsCode"));
        cacheJiKuGroup.setPartsName(json.getString("partsName"));
        cacheJiKuGroup.setSpec(json.getString("spec"));
        cacheJiKuGroup.setUnitName(json.getString("unitName"));
        for (JiKuGroupItem stockDTO : cacheJiKuGroup.getStockDTOs()) {
            JSONArray stockDTOs = json.getJSONArray("stockDTOs");
            for (Object o : stockDTOs) {
                JSONObject dto = (JSONObject)o;
                if (stockDTO.getStockId() == dto.getIntValue("stockId")) {
                    stockDTO.setStockNum(dto.getDoubleValue("stockNum"));
                    stockDTO.setSalesPrice(dto.getBigDecimal("salesPrice").doubleValue());
                }
            }
        }
    }

    private boolean checkImportantUpdate(JSONObject json, Map oldJiKuGroup) {
        return importantFields.stream().anyMatch(field -> {
            return !checkEqual(json.getString(field), oldJiKuGroup.get(field) != null ? oldJiKuGroup.get(field).toString() : null);
        });
    }

    /***
     * 用于比较两个字符串是否相等
     */
    private boolean checkEqual(String str, String str1) {
        if (StringUtils.isEmpty(str) && StringUtils.isEmpty(str1)) return true;
        if (str == null || str1 == null) return false;
        return str.equals(str1);
    }
    private void todos(JSONArray newJiKuGroups, SupplierPlatformItem supplierPlatformItem, String property, Map map) {
        if (newJiKuGroups.size() == 0 ) return;

        JSONObject param = new JSONObject();
        param.put("property", property);
        param.put("supplierPlatformItemId", supplierPlatformItem.getId());
        List<JSONObject> collect = newJiKuGroups.stream().map(o -> {
            JSONObject newJiKuGroup = (JSONObject) o;
            Map oldJiKuGroup = (Map) map.get(newJiKuGroup.getString("partsId"));
            JSONObject todo =  new JSONObject();
            JSONObject supplierItem = new JSONObject();
            supplierItem.put("id", supplierPlatformItem.getId());
            todo.put("source", String.valueOf(Math.abs(newJiKuGroup.getIntValue("partsId"))));
            todo.put("supplierPlatformItem", supplierItem);
            todo.put("oldBrandName", oldJiKuGroup != null && oldJiKuGroup.get("partsBrandName") != null ? oldJiKuGroup.get("partsBrandName").toString() : "");
            todo.put("brandName", newJiKuGroup.getString("partsBrandName"));
            todo.put("oldOriginPlace",oldJiKuGroup != null && oldJiKuGroup.get("originPlace") != null ? oldJiKuGroup.get("originPlace").toString() :"");
            todo.put("originPlace", newJiKuGroup.getString("originPlace"));
            todo.put("oldPartCode", oldJiKuGroup != null && oldJiKuGroup.get("partsCode") != null ? oldJiKuGroup.get("partsCode").toString() : "");
            todo.put("partCode", newJiKuGroup.getString("partsCode"));
            todo.put("oldPartCodeName", oldJiKuGroup != null && oldJiKuGroup.get("partsName") != null  ? oldJiKuGroup.get("partsName").toString() : "");
            todo.put("partCodeName", newJiKuGroup.getString("partsName"));
            todo.put("oldUnit", oldJiKuGroup != null && oldJiKuGroup.get("unitName") != null ? oldJiKuGroup.get("unitName").toString() : "");
            todo.put("unit", newJiKuGroup.getString("unitName"));
            todo.put("stockQty", newJiKuGroup.getJSONArray("stockDTOs").stream().mapToDouble( item ->{
                JSONObject json = (JSONObject)item;
                return json.getBigDecimal("stockNum").doubleValue();
            }).sum());
            todo.put("untaxPrice", newJiKuGroup.getJSONArray("stockDTOs").size() != 0 ? newJiKuGroup.getJSONArray("stockDTOs").stream().mapToDouble( item ->{
                JSONObject json = (JSONObject)item;
                return json.getBigDecimal("salesPrice").doubleValue();
            }).min().getAsDouble() : 0.0d);
            todo.put("batch", DateUtil.format(new Date(), DateUtil.SHOW_DATE_NUMBER_FORMAT));
            return todo;
        }).collect(Collectors.toList());
        param.put("data", collect);
        SimpleRequest request = new SimpleRequest();
        request.setData(param);
        todoService.inserts(request);
    }



    private long getHour(String cron){
        CronExpression exp;
        try {
            exp = new CronExpression(cron);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
        Date startDate = exp.getNextValidTimeAfter(new Date());
        Date endDate = exp.getNextValidTimeAfter(startDate);
        long nd = 1000 * 24 * 60 * 60;
        long nh = 1000 * 60 * 60;
        long diff = endDate.getTime() - startDate.getTime();
        // 计算差多少天
        long day = diff / nd;
        // 计算差多少小时
        long hour = ( diff % nd / nh ) + ( day * 24 );
        return hour;
    }


    public void debugging(SimpleRequest request) {
        JSONArray data = request.getJO().getJSONArray("partsDTOs");
        List<JiKuGroupDebug> list = JSONArray.parseArray(data.toString(), JiKuGroupDebug.class);
        String supplierPlatformItemId = request.getJO().getString("supplierPlatformItem");
        SupplierPlatformItem supplierPlatformItem = supplierPlatformItemRepository.findOne(supplierPlatformItemId);
        for (int i = 0; i < list.size(); i++) {
            list.get(i).setSupplierPlatformItem(supplierPlatformItem);
            list.get(i).setId(sequenceService.getId(JiKuGroupDebug.CONST_TABLE_NAME));
        }
        SpringManager.getBean(JiKuGroupDebugRepository.class).save(list);
    }

    public com.apestech.framework.json.JSONObject jiKuGroupDebugData(SimpleRequest request){
        com.apestech.framework.json.JSONObject json = new com.apestech.framework.json.JSONObject();
        try {
            JSONObject jo = request.getJO();
            for (Object condition : jo.getJSONArray("condition")) {
                if ("STATES".equals(JSON.toJSON(condition).getString("field")) && "debugging".equals(JSON.toJSON(condition).getString("value"))) {
                    jo.put("queryid", "supplierPlatformTodo.jiKuGroupDebugData");
                }
            }
            String body = jo.toString();
            json = JSON.toJSON(body);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return json;
    }

}
